主题
如果二叉树是一条链,本题就和 560. 和为 K 的子数组 完全一样了:统计有多少个非空连续子数组的元素和恰好等于
这两题的联系如下:
| 560. 和为 K 的子数组 | 437. 路径总和 III |
|---|---|
| 连续子数组 | 方向向下的路径 |
| 前缀 | 从根节点开始的路径 |
| 做法:枚举子数组右端点,统计有多少个左端点 | 做法:枚举路径的终点,统计有多少个起点 |
我们要解决的问题是:DFS 遍历这棵树,遍历到节点
和 560 题一样的套路:一边遍历二叉树,一边用哈希表
答疑
问:为什么这样做是对的?不会漏算多算吗?
答:不会漏算多算。首先最暴力的做法是,枚举终点,枚举起点,判断起点到终点的路径和是否恰好等于
问:为什么要初始化哈希表
答:同 560 题,这里的
问:为什么代码中要先更新
答:在
问:代码中的「恢复现场」用意何在?
答:举个例子,递归完
问:为什么递归参数
答:s += node.val 修改的仅仅是当前递归函数中的 s += node.val 就会影响全局了,这种情况需要写 s -= node.val 恢复现场。
问:能不能枚举起点?
答:首先对比一下,枚举终点的话,起点都在上面,都在一条链中(根到当前节点),很好维护;而枚举起点,终点都在下面(
python
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> int:
# key:从根到 node 的节点值之和
# value:节点值之和的出现次数
# 注意在递归过程中,哈希表只保存根到 node 的路径的前缀的节点值之和
cnt = defaultdict(int)
cnt[0] = 1
ans = 0
# s 表示从根到 node 的父节点的节点值之和(node 的节点值尚未计入)
def dfs(node: Optional[TreeNode], s: int) -> None:
if node is None:
return
nonlocal ans
s += node.val
# 把 node 当作路径的终点,统计有多少个起点
ans += cnt[s - targetSum]
cnt[s] += 1
dfs(node.left, s)
dfs(node.right, s)
cnt[s] -= 1 # 恢复现场(撤销 cnt[s] += 1)
dfs(root, 0)
return anscpp
// C++ 版待补充cpp
class Solution {
public:
int pathSum(TreeNode* root, int targetSum) {
// key:从根到 node 的节点值之和
// value:节点值之和的出现次数
// 注意在递归过程中,哈希表只保存根到 node 的路径的前缀的节点值之和
unordered_map<long long, int> cnt = {{0, 1}};
int ans = 0;
// lambda 递归
// s 表示从根到 node 的父节点的节点值之和(node 的节点值尚未计入)
auto dfs = [&](this auto&& dfs, TreeNode* node, long long s) {
if (node == nullptr) {
return;
}
s += node->val;
// 把 node 当作路径的终点,统计有多少个起点
ans += cnt[s - targetSum]; // 注意这样写会把 s-targetSum 插入哈希表,介意的话可以特判
cnt[s]++;
dfs(node->left, s);
dfs(node->right, s);
cnt[s]--; // 恢复现场(撤销 cnt[s]++)
};
dfs(root, 0);
return ans;
}
};复杂度分析
- 时间复杂度:
,其中 是二叉树的节点个数。 - 空间复杂度:
。
分类题单
- 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
- 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
- 单调栈(基础/矩形面积/贡献法/最小字典序)
- 网格图(DFS/BFS/综合应用)
- 位运算(基础/性质/拆位/试填/恒等式/思维)
- 图论算法(DFS/BFS/拓扑排序/最短路/最小生成树/二分图/基环树/欧拉路径)
- 动态规划(入门/背包/状态机/划分/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
- 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
- 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
- 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
- 【本题相关】链表、树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA)
- 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)
欢迎关注 B站@灵茶山艾府